#pragma once
#include "Sock.hpp"
#include <cstdint>
#include<iostream>
#include<functional>
#include <pthread.h>
#include<vector>
#include<unistd.h>

namespace yangyi
{
    using func_t=std::function<void(int)>;
    class TcpServer;

    class ThreadData
    {
    public:
        ThreadData(int sock,TcpServer* server)
        :_sock(sock),_server(server)
        {

        }
        ~ThreadData(){}
    public:
        int _sock;
        TcpServer* _server;
    };
    
    class TcpServer
    {
    public:
        TcpServer(uint16_t& port,std::string& ip)
        {
            _serversock=_sock.Socket();
            _sock.Bind(_serversock, port, ip);
            _sock.Listen(_serversock);
        }
        //开始向任务队列里面存放任务
        void WorkerBind(func_t func)
        {
            _func.push_back(func);
        }
        void Excute(int sock)
        {
            for(auto& iter:_func){
                iter(sock);
            }
        }
        void Start()
        {
            while(true)
            {
                uint16_t clientport;
                std::string clientip;
                int sock;
                _sock.Accept(_serversock, &clientport, &clientip);
                if(sock == -1){
                    continue;
                }
                pthread_t tid;
                ThreadData* td=new ThreadData(sock,this);
                pthread_create(&tid, nullptr, ThreadRoutine, (void*)td);
            }
        }
        ~TcpServer(){
            if(_serversock >= 0){
                close(_serversock);
            }
        }
    private:
        static void* ThreadRoutine(void* args)
        {
            pthread_detach(pthread_self());
            ThreadData* td=static_cast<ThreadData*>(args);
            td->_server->Excute(td->_sock);
            close(td->_sock);
            return nullptr;
        }
    private:
        int _serversock;
        Sock _sock;
        std::vector<func_t> _func;
    };
}
